﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Reflection;
using Sofire.DataComm.Remoting.Server.Settings;

namespace Sofire.DataComm.Remoting.Server
{
    /// <summary>
    /// 表示远程过程中的客户当前上下文，一个上下文基于一次连接。
    /// </summary>
    public sealed class RemotingContext : IDisposable
    {
        [ThreadStatic]
        internal static RemotingContext _Current;
        /// <summary>
        /// 获取当前线程中的上下文。上下文指的是一个正在与服务器进行连接的客户。
        /// </summary>
        public static RemotingContext Current
        {
            get
            {
                return _Current;
            }
            internal set
            {
                _Current = value;
                RemotingApplication.ActivingContext(value);
            }
        }

        internal Socket _Client;

        private IServer _Server;
        /// <summary>
        /// 获取当前上下文关联的服务器。
        /// </summary>
        public IServer Server
        {
            get
            {
                return this._Server;
            }
        }

        private string _ClientEndPoint;
        /// <summary>
        /// 获取当前上下文格式为“ip:port”的地址。
        /// </summary>
        public string ClientEndPoint
        {
            get
            {
                if(this._ClientEndPoint == null)
                {
                    try
                    {
                        this._ClientEndPoint = this._Client.RemoteEndPoint.ToString();
                    }
                    catch(Exception) { }
                }
                return this._ClientEndPoint;
            }
        }

        private InvokingInfo _Invoking;
        /// <summary>
        /// 获取当前上下文中正在调用的信息。在非契约方法调用时，将返回一个 null 值。
        /// </summary>
        public InvokingInfo Invoking
        {
            get
            {
                return this._Invoking;
            }
        }

        internal RemotingCertificate _Certificate;
        /// <summary>
        /// 获取客户端凭证。
        /// </summary>
        public RemotingCertificate Certificate
        {
            get
            {
                return this._Certificate;
            }
        }

        internal ServiceSetting _ServiceSetting;
        /// <summary>
        /// 获取访问地址对应的服务端配置。
        /// </summary>
        public ServiceSetting ServiceSetting
        {
            get
            {
                return this._ServiceSetting;
            }
        }

        internal string _SessionID;
        /// <summary>
        /// 获取会话编号。
        /// </summary>
        public string SessionID
        {
            get
            {
                return this._SessionID;
            }
        }

        internal SessionEntry _SessionEntry;
        /// <summary>
        /// 设置或获取会话缓存数据。当设置的值为 null 时，则移除这个缓存。
        /// </summary>
        /// <param name="key">缓存标识。</param>
        /// <returns>如果当前会话存在缓存标识，则返回缓存值，否则返回 null 值。</returns>
        public object this[string key]
        {
            get
            {
                if(this._SessionEntry == null) return null;
                object value;
                this._SessionEntry.TryGetValue(key, out value);
                return value;
            }
            set
            {
                if(this._SessionEntry == null) return;
                if(value == null) this._SessionEntry.Remove(key);
                else this._SessionEntry[key] = value;
            }
        }

        /// <summary>
        /// 清空会话缓存数据。
        /// </summary>
        public void SessionClear()
        {
            if(this._SessionEntry == null) return;
            this._SessionEntry.Clear();
        }

        /// <summary>
        /// 重置会话缓存，在下一次使用时候
        /// </summary>
        public void SessionReset()
        {
            if(this._SessionEntry == null) return;
            Settings.ServiceSetting.Cache.Remove(this._SessionID);
        }

        /// <summary>
        /// 获取会话线程访问。
        /// </summary>
        public object SessionSyncRoot
        {
            get
            {
                if(this._SessionEntry == null) return this;
                return this._SessionEntry.SyncRoot;
            }
        }

        private DateTime _LastActivedTime;
        /// <summary>
        /// 获取一个值，表示客户最后的活动时间。
        /// </summary>
        public DateTime LastActivedTime
        {
            get
            {
                return this._LastActivedTime;
            }
        }

        private DateTime _JoinedTime;
        /// <summary>
        /// 表示加入的时间。
        /// </summary>
        public DateTime JoinedTime
        {
            get
            {
                return this._JoinedTime;
            }
        }

        private bool _IsActived = true;
        /// <summary>
        /// 获取一个值，表示当前上下文是否正在活动。
        /// </summary>
        public bool IsActived
        {
            get
            {
                return this._IsActived;
            }
        }

        private bool _IsValidUser = true;
        /// <summary>
        /// 设置或获取一个值，表示当前上下文是否合法。默认为 true，表示合法。
        /// </summary>
        public bool IsValidUser
        {
            get
            {
                return this._IsValidUser;
            }
            set
            {
                this._IsValidUser = value;
            }
        }

        private object _Tag;
        /// <summary>
        /// 设置或获取一个值，表示一个数据。
        /// </summary>
        public object Tag
        {
            get
            {
                return this._Tag;
            }
            set
            {
                this._Tag = value;
            }
        }


        /// <summary>
        /// 表示上下文的调用信息。
        /// </summary>
        public class InvokingInfo
        {
            internal InvokingInfo() { }

            internal WeakReference _Method;
            /// <summary>
            /// 获取表示当前正在调用的方法。
            /// </summary>
            public MethodInfo Method
            {
                get
                {
                    if(this._Method == null || !this._Method.IsAlive) return null;
                    return this._Method.Target as MethodInfo;
                }
            }

            internal WeakReference _MethodParameters;
            /// <summary>
            /// 获取表示当前正在调用的方法参数值。
            /// </summary>
            public object[] MethodParameters
            {
                get
                {
                    if(this._MethodParameters == null || !this._MethodParameters.IsAlive) return null;
                    return this._MethodParameters.Target as object[];
                }
            }
        }

        internal RemotingContext(IServer server, Socket clent)
        {
            this._JoinedTime = DateTime.Now;
            this._Server = server;
            this._Client = clent;
            RemotingContext.Current = this;
        }

        internal void Activing()
        {
            this._LastActivedTime = DateTime.Now;
        }

        internal void SetLastInvoke(MethodInfo methodInfo, object[] parameters)
        {
            this.Activing();
            this._Invoking = new InvokingInfo()
            {
                _Method = new WeakReference(methodInfo),
                _MethodParameters = parameters == null ? null : new WeakReference(parameters),
            };
        }

        internal void CleatActivingInvoke()
        {
            this._Invoking = null;
        }

        void IDisposable.Dispose()
        {
            if(this._IsActived)
            {
                this._IsActived = false;
                RemotingApplication.InactivingContext(this);
                this._Client = null;
                this._Server = null;
            }
        }
    }
}
